package com.yiyi.credit.manage.abutment.common.utils;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


public class DateUtil {
    public static final String DATE_TIME_PATTERN = "YYYY-MM-dd HH:mm:ss";
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    private static final Logger logger = LoggerFactory.getLogger(DateUtil.class);

    public static Date parseDate(String string) throws ParseException {
        return new SimpleDateFormat(DATE_PATTERN).parse(string);
    }

    public static String getToday() {
        return formatDate(new Date());
    }


    public static String getDate2(int addDays) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.add(Calendar.DAY_OF_YEAR, addDays);
        return formatDate(calendar.getTime());
    }


    public static Timestamp getThisDate() throws ParseException {
        Timestamp thisdate = new Timestamp(new Date().getTime());
        return thisdate;
    }

    public static String dateToString(String formatString, Date date) {
        SimpleDateFormat dateformat = new SimpleDateFormat(formatString);

        return dateformat.format(date);
    }


    public static Date convertString2Date(String str, String pattern) {
        if (str == null || "".equals(str)) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        Calendar calendar = Calendar.getInstance();
        try {
            calendar.setTime(sdf.parse(str.trim()));
        } catch (ParseException ex) {
            logger.error(ex.getMessage(), ex);
        }
        return calendar.getTime();
    }


    public static String convertDate2String(Date date, String pattern) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }


    public static String format(Date date) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_PATTERN);
        return sdf.format(date);
    }

    public static String formatDate(Date date) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
        return sdf.format(date);
    }


    public static int compareTo(Date first, Date second) {
        if (first == null || second == null)
            return 2;
        else
            return first.compareTo(second);
    }


    public static Date addYear(Date date, int year) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, year);
        return calendar.getTime();
    }


    public static Date addMonth(Date date, int month) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);
        return calendar.getTime();
    }


    public static Date addDay(Date date, int day) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, day);
        return calendar.getTime();
    }


    public static Date addHour(Date date, int hour) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR_OF_DAY, hour);
        return calendar.getTime();
    }


    public static Date addMinute(Date date, int minute) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        return calendar.getTime();
    }


    public static Date getSystemDate() {
        return new Date();
    }


    public static boolean isValidDate(Object date, String pattern) {
        if (date == null || pattern == null) {
            return false;
        }

        if (date.toString().length() != pattern.length()) {
            return false;
        }

        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            sdf.setLenient(false);
            sdf.parse(String.valueOf(date));
        } catch (ParseException ex) {
            return false;
        }
        return true;
    }


    public static String getHHMMSSS() {
        return DateFormat.getTimeInstance().format(new Date());
    }


    public static int getDays(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.getActualMaximum(Calendar.DATE);
    }


    public static int getDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DATE);
    }


    public static String getYMD(Date date, String pattern) {
        if (date == null)
            date = getSystemDate();

        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        String ymd = sdf.format(date);
        if (pattern.contains("/") || pattern.contains("-"))
            return ymd.substring(0, 10);
        else
            return ymd.substring(0, 8);
    }


    public static int daysOfTwo(Date fDate, Date oDate) {

        Calendar aCalendar = Calendar.getInstance();

        aCalendar.setTime(fDate);

        int day1 = aCalendar.get(Calendar.DAY_OF_YEAR);

        aCalendar.setTime(oDate);

        int day2 = aCalendar.get(Calendar.DAY_OF_YEAR);

        return day2 - day1;

    }


    public static int dayGap(Long t1, Long t2) {
        if (t1 == null || t2 == null)
            return 0;
        Calendar calendar = Calendar.getInstance();

        calendar.setTimeInMillis(t1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        long between_days = (t2 - calendar.getTimeInMillis()) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }


    public static Long getStartTime() {
        Calendar todayStart = Calendar.getInstance();
        todayStart.set(Calendar.HOUR_OF_DAY, 0);
        todayStart.set(Calendar.MINUTE, 0);
        todayStart.set(Calendar.SECOND, 0);
        todayStart.set(Calendar.MILLISECOND, 0);
        return todayStart.getTime().getTime();
    }

    public static Long getEndTime() {
        Calendar todayEnd = Calendar.getInstance();
        todayEnd.set(Calendar.HOUR_OF_DAY, 23);
        todayEnd.set(Calendar.MINUTE, 59);
        todayEnd.set(Calendar.SECOND, 59);
        todayEnd.set(Calendar.MILLISECOND, 999);
        return todayEnd.getTime().getTime();
    }

    public static long[] getDayStartAndEnd(int addDay) {
        return getDayStartAndEnd(new Date(), addDay);
    }

    public static long[] getDayStartAndEnd(Date date, int addDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        if (addDay != 0)
            calendar.add(Calendar.DAY_OF_YEAR, addDay);
        long[] se = new long[2];
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        se[0] = calendar.getTimeInMillis();

        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        se[1] = calendar.getTimeInMillis();
        return se;
    }

    public static List<String> monthlyByPeriod(Long startTime, Integer period) {
        if (startTime == null || period == null)
            return Collections.emptyList();

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(startTime);
        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd");
        List<String> strings = new ArrayList<>();
        for (int i = 1; i <= period; i++) {
            String time2 = format2.format(calendar.getTime());
            calendar.add(Calendar.MONTH, 1);
            strings.add(time2);
        }
        return strings;

    }


    public static Map<Integer, Integer> getDaysOfMonth(long start, long end) {
        if (dayGap(start, end) <= 0) {
            return Collections.emptyMap();
        }

        Map<Integer, Integer> months = new HashMap<>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(end);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        String yearMonth = String.valueOf(year).concat(
                month < 10 ?
                        String.valueOf("0").concat(String.valueOf(month)) :
                        String.valueOf(month)
        );
        months.put(month, day);

        calendar.setTimeInMillis(start);
        int currentYear = calendar.get(Calendar.YEAR);
        int currentMonth = calendar.get(Calendar.MONTH) + 1;
        int currentDay = calendar.get(Calendar.DAY_OF_MONTH);
        months.put(currentMonth, calendar.getActualMaximum(Calendar.DAY_OF_MONTH) - currentDay);

        if (currentYear == year && currentMonth == month) {
            months.clear();
            months.put(currentMonth, day - currentDay);
            return months;
        }

        currentMonth++;
        String currentYearMonth = String.valueOf(currentYear).concat(
                currentMonth < 10 ?
                        String.valueOf("0").concat(String.valueOf(currentMonth)) :
                        String.valueOf(currentMonth)
        );
        while (currentYearMonth.compareTo(yearMonth) < 0) {
            calendar.add(Calendar.MONTH, 1);
            currentMonth = calendar.get(Calendar.MONTH) + 1;
            currentYear = calendar.get(Calendar.YEAR);
            currentYearMonth = String.valueOf(currentYear).concat(
                    currentMonth < 10 ?
                            String.valueOf("0").concat(String.valueOf(currentMonth)) :
                            String.valueOf(currentMonth)
            );
            if (currentYearMonth.compareTo(yearMonth) >= 0)
                break;
            months.put(currentMonth, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        }

        return months;
    }

    public static boolean isYesterday(long timeMillions) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        return isSameDay(timeMillions, calendar.getTimeInMillis());
    }


    public static boolean isToday(long timeMillions) {
        return isSameDay(timeMillions, System.currentTimeMillis());
    }

    public static boolean isSameDay(long time1, long time2) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String s1 = simpleDateFormat.format(new Date(time1));
        String s2 = simpleDateFormat.format(new Date(time2));
        return StringUtils.equals(s1, s2);
    }

    public static String getDateString(int addDays) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, addDays);
        return new SimpleDateFormat("yyyyMMdd").format(calendar.getTime());
    }


}
